package com.yeah.sinaspider.service.impl;

import com.yeah.sinaspider.dingtalk.service.DingtalkService;
import com.yeah.sinaspider.mapper.SysCatMapper;
import com.yeah.sinaspider.service.OperateConstants;
import com.yeah.sinaspider.service.WeiboService;
import com.yeah.sinaspider.utils.CollUtils;
import com.yeah.sinaspider.utils.DateUtils;
import com.yeah.sinaspider.vo.LoginParam;
import com.yeah.sinaspider.vo.SysCatVo;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @FileName WeiboServiceImpl.java
 * @Description TODO
 * @Author yeah、一页
 * @Email 1324459373@qq.com|quhailong1995@gmail.com
 * @Date 2020/4/19 14:41
 * @Version 1.0
 */
@Service
public class WeiboServiceImpl implements WeiboService {


    private final static Logger logger = LoggerFactory.getLogger(WeiboServiceImpl.class);

    @Autowired
    private DingtalkService dingtalkService;

    @Autowired
    private SysCatMapper sysCatMapper;

    private final static String[] contents = {"为什么平胸妹子一般都是吃货？答：因为穷胸极饿！"
            ,"怎样含蓄地表达“我已经被收买了”？神回复：我说句公道话……"
            ,"为什么在洗完澡洗完头之后，一些人会觉得自己变帅/变漂亮了许多？答：脑子进水了。"
            ,"你离死亡最近的一次经历是什么？回复：二十年前，差点让后面的那群jing子追上。"
            ,"问中国哪里的姑娘最漂亮？神回复：微信朋友圈"
            ,"记得那是上个星期天吧，我看到你走到一堆便便前，蹲下来戳了戳，很疑惑，摸了摸还是很疑惑，闻了闻好像是便便，最后放到嘴里尝了尝，确定是便便，然后站起来高兴叫道：“哈哈，幸好没踩到！"
            ,"头一次评论啊，好紧张啊，该怎么说啊，打多少字才显的有文采啊，这样说好不好啊，会不会成热门啊，我写的这么好会不会太招遥，写的这么深奥别人会不会看不懂啊，怎样才能写出飘逸潇洒的水平呢，半小时写了这么多会不会太快啊，好激动啊！"
            ,"全都是泡沫゜○。○゜。Ｏ°ｏ○。ｏ゜○。゜Ｏ○。°゜Ｏ○。°○ｏ°○ｏ○゜ｏ。Ｏ゜○。゜。゜○。○゜。Ｏ°ｏ○。ｏ゜゜○。○゜。Ｏ°ｏ○。ｏ゜○。゜Ｏ○。°゜Ｏ○。°○ｏ°○ｏ○゜ｏ。Ｏ゜○。゜。゜○。○゜。Ｏ°ｏ○。ｏ゜゜○。○゜。Ｏ°ｏ○。ｏ゜○。゜Ｏ○。°゜Ｏ○。°○ｏ°○ｏ○゜ｏ。Ｏ゜○。゜。゜○。○゜。Ｏ°ｏ○。ｏ゜゜○。○゜。Ｏ°ｏ○。ｏ゜○。゜Ｏ○。°゜Ｏ○。°○ｏ°○ｏ○゜ｏ。Ｏ゜○。゜。゜○。○゜。Ｏ°ｏ○。ｏ゜゜○。"
            ,"太无聊了"
            ,"一定要成功，希望遇到有缘人"
    };

    private final static String[] feels = {"[笑而不语]","[鼓掌]","[爱你]","[可爱]","[笑而不语]","[太开心]","[黑线]","[委屈]"};

    private static Map<String,Boolean> remMap = new HashMap<>();


    @Override
    public RemoteWebDriver loginByAccount(LoginParam loginParam, RemoteWebDriver driver,String driverKey) throws Exception {

        driver.get(getCatNmByCd(OperateConstants.weibo_login_page_url));

        WebDriverWait webDriverWait = new WebDriverWait(driver, 10);
        webDriverWait.until(new ExpectedCondition<WebElement>() {
            @Override
            public WebElement apply(WebDriver webDriver) {
                try {
                    return webDriver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_account_login_btn)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });

        driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_account_login_username))).sendKeys(loginParam.getUsername());
        Thread.sleep(2000);

        driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_account_login_password))).sendKeys(loginParam.getPassword());
        Thread.sleep(2000);

        if(StringUtils.hasText(loginParam.getVcode())){
            driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_account_login_vcode))).sendKeys(loginParam.getVcode());
            Thread.sleep(2000);
        }

        //点击
        driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_account_login_btn))).click();
        Thread.sleep(4000);

//        String base64Str = null;
//        ImageInputStream iis = null;
//        try {
//            byte[] screenshotAs = driver.getScreenshotAs(OutputType.BYTES);
//            iis = ImageIO.createImageInputStream(new ByteArrayInputStream(screenshotAs));
//            ImageReader reader = ImageIO.getImageReaders(iis).next();
//            reader.setInput(iis, true);
//            ImageReadParam param = reader.getDefaultReadParam();
//
//            Rectangle rect = new Rectangle(login_btn.getLocation().x,login_btn.getLocation().y-1000,login_btn.getSize().width, login_btn.getSize().height+1000);
//            param.setSourceRegion(rect);
//            BufferedImage bufferedImage = reader.read(0, param);
//
//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//            ImageIO.write(bufferedImage, "png", baos);
//
//            base64Str = Base64Utils.encodeToString(baos.toByteArray());
//        }catch (Exception e){
//            e.printStackTrace();
//        }finally {
//            try {
//                iis.close();
//            }catch (Exception e){
//                e.printStackTrace();
//            }
//        }
        return driver;
    }

    @Override
    public RemoteWebDriver loginByQR(RemoteWebDriver driver,String driverKey) throws Exception {
        driver.get(getCatNmByCd(OperateConstants.weibo_login_page_url));
        WebDriverWait webDriverWait = new WebDriverWait(driver, 10);
        webDriverWait.until(new ExpectedCondition<WebElement>() {
            @Override
            public WebElement apply(WebDriver webDriver) {
                try {
                    return webDriver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_qr_login_btn)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });

        driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_login_qr_login_btn))).click();
        Thread.sleep(1000);

        return driver;
    }

    @Override
    public void execAutoComment(RemoteWebDriver driver,String driverKey) throws InterruptedException {

        //评论可选内容
        List<String> comment_contents = getCommentContentsByCd(OperateConstants.comment_contents+"-"+driverKey);
        if(CollUtils.isEmpty(comment_contents)){
            //默认内容
            comment_contents = Arrays.asList(contents);
        }

        exec(driver,driverKey, comment_contents);


    }


    private void exec(RemoteWebDriver driver,String driverKey,List<String> comment_contents) throws InterruptedException {

        logger.info("########################################## Driver"+driverKey+" 任务开始#############################################################");
        String mark1 = "---remMap:["+remMap.size()+"]---";
        logger.info("--------------------------"+mark1+"------------------------");


        StringBuffer mark2 = new StringBuffer();
        StringBuffer mark3 = new StringBuffer();

        try {
            driver.get(getCatNmByCd(OperateConstants.comment_url));

            WebDriverWait webDriverWait1 = new WebDriverWait(driver, 10);
            webDriverWait1.until((ExpectedCondition<WebElement>) webDriver -> {
                try {
                    return webDriver.findElement(By.xpath(getCatNmByCd(OperateConstants.expected_element_xpath)));
                } catch (Exception e) {
                    mark3.append(e.getMessage()).append("\n\n\n");
                    e.printStackTrace();
                }
                return null;
            });

            Thread.sleep(1000);

            //选前四条进行评论

            String key = "";
            String content = "";
            long timeCount;
            for(int i=1;i<=4;i++){

                timeCount = System.currentTimeMillis();

                String tempPrt = "";

                try {
                    //微博条目
                    String feedContentXPath = getCatNmByCd(OperateConstants.weibo_item_xpath)+"["+i+"]";
                    WebElement feedContent = driver.findElementByXPath(feedContentXPath);

                    //
                    String mid = feedContent.getAttribute("mid");
                    //作者
                    String author = feedContent.findElement(By.xpath(feedContentXPath+getCatNmByCd(OperateConstants.weibo_item_author_xpath))).getText();

                    key = author+"---"+mid;
                    content = comment_contents.get(new Random().nextInt(comment_contents.size()))+feels[new Random().nextInt(feels.length)];

                    if(remMap.get(key)!=null&&remMap.get(key)){
                        mark3.append(String.format("重复微博，无需评论，key[%s]",key)).append("\n\n\n");
                    }else {

                        int tt = new Random().nextInt(4);
                        //点击评论按钮
                        feedContent.findElement(By.xpath(feedContentXPath+getCatNmByCd(OperateConstants.weibo_item_comment_show_xpath))).click();
                        Thread.sleep(3000+tt*1000);

                        //评论内容输入区
                        feedContent.findElement(By.xpath(feedContentXPath+getCatNmByCd(OperateConstants.weibo_item_comment_textarea_xpath))).sendKeys(content);
                        Thread.sleep(8000+tt*1000);

                        //提交按钮
                        feedContent.findElement(By.xpath(feedContentXPath+getCatNmByCd(OperateConstants.weibo_item_comment_btn_xpath))).click();
                        Thread.sleep(3000+tt*1000);

                        //if(testNewWindow(driver)){
                        if(false){
                            tempPrt = String.format("评论失败---->key[%s]，msg[%s]",key
                                    ,driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_item_comment_alert_error1))).getText());
                            mark3.append(tempPrt).append("\n\n\n");
                        }else {

                            driver.findElement(By.xpath(getCatNmByCd(OperateConstants.weibo_item_comment_success_flag+"-"+driverKey)));

                            tempPrt = String.format("评论成功---->key[%s]，content[%s]",key,content);
                            mark2.append(tempPrt).append("\n").append("耗时："+(System.currentTimeMillis()-timeCount)/1000).append("\n\n\n");
                            remMap.put(key,true);
                        }

                    }

                }catch (Exception e){
                    tempPrt = String.format("评论失败---->key[%s]，msg[%s]",key,e.getMessage());
                    mark3.append(tempPrt).append("\n").append("耗时："+(System.currentTimeMillis()-timeCount)/1000).append("\n\n\n");
                }

                logger.info(tempPrt+"   耗时："+(System.currentTimeMillis()-timeCount)/1000);

                int times = new Random().nextInt(10) * 1000 * 2 + 20000;
                logger.info("休眠："+times);
                Thread.sleep(times);
            }

        }catch (Exception e){
            mark3.append("评论失败--->"+e.getMessage()).append("\n\n\n");
            e.printStackTrace();
        }

        try {
            HashMap<String, Object> dingMap = new HashMap<>();
            dingMap.put("userIds", "manager4701");
            dingMap.put("bodyContent",
                    mark1 + "\n"
                    +"### Driver ###\n"
                    +driverKey+"\n"
                    +"### 成功 ###\n"
                    + mark2.toString()+"\n"
                    +"### 失败 ###\n"
                    + mark3.toString()+"\n"
                    + DateUtils.format(new Date(),DateUtils.VAL_TIMESTAMP_FORMAT));
            dingtalkService.pushOaWorkMsg(dingMap);
        } catch (Exception e) {
            logger.info("钉钉推送失败---->"+e.getMessage());
            e.printStackTrace();
        }


        logger.info("########################################## Driver"+driverKey+" 任务结束#############################################################");

    }


    private Optional<SysCatVo> findCatByCd(String cd){
        Example<SysCatVo> example = Example.of(new SysCatVo(cd));
        Optional<SysCatVo> sysCatMapperOne = sysCatMapper.findOne(example);
        return sysCatMapperOne;
    }

    private String getCatNmByCd(String cd) throws Exception {
        Example<SysCatVo> example = Example.of(new SysCatVo(cd));
        Optional<SysCatVo> sysCatMapperOne = sysCatMapper.findOne(example);
        if(!sysCatMapperOne.isPresent())throw new Exception(cd+"---not find");
        return sysCatMapperOne.get().getNm();
    }

    private List<SysCatVo> findCatByPid(Long pid){
        Example<SysCatVo> example = Example.of(new SysCatVo(pid));
        return sysCatMapper.findAll(example);
    }

    private List<String> getCommentContentsByCd(String cd){
        Optional<SysCatVo> catByCd = findCatByCd(cd);
        if(!catByCd.isPresent())return null;
        List<SysCatVo> sysCatVoList = findCatByPid(catByCd.get().getId());
        if(CollUtils.isNotEmpty(sysCatVoList))return sysCatVoList.stream().map(item->item.getNm()).collect(Collectors.toList());
        return null;
    }

    //处理潜在的1个alert（javascript弹出框）
    public boolean dealPotentialAlert(WebDriver driver,boolean option) {
        //是否存在
        boolean flag = false;
        //异常捕获
        try {
            Alert alert = driver.switchTo().alert();
            //判断是否存在alert弹框
            if (null == alert){
                throw new NoAlertPresentException();
            }
            //异常捕获
            try {
                //确认or取消
                if (option) {
                    //确认
                    alert.accept();
                    System.out.println("Accept the alert: " + alert.getText());
                } else {
                    //取消
                    alert.dismiss();
                    System.out.println("Dismiss the alert: " + alert.getText());
                }
                flag = true;
            } catch (WebDriverException e) {
                if (e.getMessage().startsWith("Could not find")){
                    System.out.println("There is no alert appear!");
                }else{
                    throw e;
                }
            }
        } catch (NoAlertPresentException e) {
            System.out.println("There is no alert appear!");
        }
        return flag;
    }


    //处理多个非alert弹窗
    public static boolean testNewWindows(WebDriver driver){
        //当前窗口句柄
        String currentHandle = driver.getWindowHandle();
        //得到所有窗口的句柄
        Set handles = driver.getWindowHandles();
        //不包括当前窗口
        handles.remove(currentHandle);
        //存在窗口
        if (handles.size() > 0) {
            try{
                //定位窗口
                driver.switchTo().window((String) handles.iterator().next());
                return true;
            }catch(Exception e){
                System.out.println(e.getMessage());
                return false;
            }
        }
        System.out.println("Did not find window");
        return false;
    }

    //处理单个非alert弹窗
    public static boolean testNewWindow(WebDriver driver){
        try{

            Set handles1 = driver.getWindowHandles();

            String aa = driver.getWindowHandle();
            driver.getWindowHandles().remove(aa);

            Set handles2 = driver.getWindowHandles();

            //定位窗口
            driver.switchTo().window(driver.getWindowHandles().iterator().next());

            return true;
        }catch(Exception e){
            System.out.println(e.getMessage());
            return false;
        }
    }

}
